package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constant.ProductConstant;
import com.atguigu.common.to.HasStockVo;
import com.atguigu.common.to.SkuReductionTo;
import com.atguigu.common.to.SkuSearchVo;
import com.atguigu.common.to.SpuBoundsTo;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.CouponFeignService;
import com.atguigu.gulimall.product.feign.SearchFeignService;
import com.atguigu.gulimall.product.feign.WareFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    private SpuInfoDescService spuInfoDescService;

    @Autowired
    private SpuImagesService spuImagesService;

    @Autowired
    private ProductAttrValueService productAttrValueService;

    @Autowired
    private AttrService attrService;

    @Autowired
    private SkuInfoService skuInfoService;

    @Autowired
    private SkuImagesService skuImagesService;

    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    private CouponFeignService couponFeignService;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private WareFeignService wareFeignService;

    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryByConditionsPage(Map<String, Object> params) {

        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();

        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)){
            wrapper.and(w->w.eq("id",key)).or().like("spu_name",key);
        }

        String catelogId = (String) params.get("catelogId");
        if (StringUtils.isNotEmpty(catelogId) && Integer.parseInt(catelogId) != 0){
            wrapper.eq("catalog_id",catelogId);
        }

        String brandId = (String) params.get("brandId");
        if (StringUtils.isNotEmpty(brandId) && Integer.parseInt(brandId) != 0){
            wrapper.eq("brand_id",brandId);
        }

        String status = (String) params.get("status");
        if (StringUtils.isNotEmpty(status)){
            wrapper.eq("publish_status",status);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    //TODO 高级部分完善0
    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo vo) {
        //1、保存spu基本信息 pms_spu_info
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(vo, spuInfoEntity);
        Date createTime = new Date();
        spuInfoEntity.setCreateTime(createTime);
        spuInfoEntity.setUpdateTime(createTime);
        this.save(spuInfoEntity);

        //2、保存spu的描述信息 pms_spu_info_desc
        List<String> decript = vo.getDecript();
//        List<SpuInfoDescEntity> collect = decript.stream().map(item -> {
//            SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
//            spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
//            spuInfoDescEntity.setDecript(item);
//            return spuInfoDescEntity;
//        }).collect(Collectors.toList());
//
//        spuInfoDescService.saveBatch(collect);
        SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
        spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
        spuInfoDescEntity.setDecript(String.join(",",decript));
        spuInfoDescService.save(spuInfoDescEntity);


        //3、保存spu的图集 pms_spu_images
        List<String> images = vo.getImages();
        if(images != null && images.size() > 0){
            List<SpuImagesEntity> imgs = images.stream().map(item -> {
                SpuImagesEntity spuImagesEntity = new SpuImagesEntity();
                spuImagesEntity.setSpuId(spuInfoEntity.getId());
                spuImagesEntity.setImgUrl(item);
                return spuImagesEntity;
            }).collect(Collectors.toList());

            spuImagesService.saveBatch(imgs);
        }

        //4、保存基本属性信息（规格参数） pms_product_attr_value
        List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
        if (baseAttrs != null && baseAttrs.size() > 0){
            List<ProductAttrValueEntity> productAttrValueEntities = baseAttrs.stream().map(item -> {
                ProductAttrValueEntity attrValueEntity = new ProductAttrValueEntity();
                attrValueEntity.setAttrId(item.getAttrId());
                attrValueEntity.setAttrValue(item.getAttrValues());
                attrValueEntity.setQuickShow(item.getShowDesc());
                attrValueEntity.setSpuId(spuInfoEntity.getId());
                AttrEntity attrEntity = attrService.getById(item.getAttrId());
                attrValueEntity.setAttrName(attrEntity.getAttrName());
                return attrValueEntity;
            }).collect(Collectors.toList());
            productAttrValueService.saveBatch(productAttrValueEntities);
        }

        //5、保存spu的积分信息 gulimall_sms:sms_spu_bounds TODO
        Bounds bounds = vo.getBounds();
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(bounds,spuBoundsTo);
        spuBoundsTo.setSpuId(spuInfoEntity.getId());
        R result1 = couponFeignService.save(spuBoundsTo);
        if (result1.getCode() != 0){
            throw new RuntimeException("远程保存spu积分信息失败");
        }


        //5、保存当前spu对应的所有sku信息
        //5.1 保存sku基本信息   pms_sku_info
        List<Skus> skus = vo.getSkus();
        skus.forEach(item->{
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            BeanUtils.copyProperties(item,skuInfoEntity);
            skuInfoEntity.setSpuId(spuInfoEntity.getId());
            skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
            skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
            skuInfoEntity.setPrice(new BigDecimal(item.getPrice()));
            skuInfoEntity.setSaleCount(0L);
            List<Images> skuImgs = item.getImages();
            Images defaultImg = null;
            List<Images> collect = skuImgs.stream().filter(item2 -> item2.getDefaultImg() == 1).collect(Collectors.toList());
            if (collect != null && collect.size() > 0){
                defaultImg = collect.get(0);
            }
            skuInfoEntity.setSkuDefaultImg(defaultImg.getImgUrl());
            skuInfoService.save(skuInfoEntity);

            //5.2 保存sku图集  pms_sku_images
            List<SkuImagesEntity> skuImagesEntities = skuImgs.stream().filter(skuImg-> StringUtils.isNotBlank(skuImg.getImgUrl())).map(skuImg -> {
                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                skuImagesEntity.setImgUrl(skuImg.getImgUrl());
                skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                skuImagesEntity.setDefaultImg(skuImg.getDefaultImg());
                return skuImagesEntity;
            }).collect(Collectors.toList());

            skuImagesService.saveBatch(skuImagesEntities);

            //5.3 保存sku的销售属性信息  pms_sku_sale_attr_value
            List<Attr> saleAttrs = item.getAttr();
            List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = saleAttrs.stream().map(saleAttr -> {
                SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                BeanUtils.copyProperties(saleAttr, skuSaleAttrValueEntity);
                AttrEntity saleAttrEntity = attrService.getById(saleAttr.getAttrId());
                skuSaleAttrValueEntity.setAttrName(saleAttrEntity.getAttrName());
                skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                return skuSaleAttrValueEntity;
            }).collect(Collectors.toList());
            skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);

            //5.4 保存sku的优惠、满减信息 gulimall_sms:sms_sku_ladder/sms_sku_full_reduction/sms_member_price TODO
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(item,skuReductionTo);
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            if (item.getFullCount().compareTo(BigDecimal.ZERO) > 0 || item.getFullPrice().compareTo(BigDecimal.ZERO) > 0) {
                couponFeignService.saveReductionInfo(skuReductionTo);
            }
            if (result1.getCode() != 0){
                throw new RuntimeException("远程保存优惠信息失败");
            }
        });



    }

    @Transactional
    @Override
    public void up(Long spuId) {

        //spu信息是多个sku共用的，放到循环外查
        List<ProductAttrValueEntity> productAttrValueEntities = productAttrValueService.listForSpu(spuId);
        List<Long> attrIds = productAttrValueEntities.stream().map(item -> item.getAttrId()).collect(Collectors.toList());
        List<AttrEntity> attrsForSearch = attrService.filterAttrSearch(attrIds);
        List<Long> attrIdsForSearch = attrsForSearch.stream().map(attrEntity -> attrEntity.getAttrId()).collect(Collectors.toList());
        HashSet<Long> longs = new HashSet<>(attrIdsForSearch);
        List<SkuSearchVo.Attr> attrValueList = productAttrValueEntities.stream().filter(item -> longs.contains(item.getAttrId())).map(item -> {
            SkuSearchVo.Attr attr = new SkuSearchVo.Attr();
            BeanUtils.copyProperties(item, attr);
            return attr;
        }).collect(Collectors.toList());

        List<SkuInfoEntity> skuInfos = skuInfoService.selectBySpuId(spuId);

        List<Long> skuIds = skuInfos.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
        Map<Long, Boolean> hasStockMap = null;
        try {
            //hasStock 需远程查询库存系统
            R hasStockResponse = wareFeignService.hasStock(skuIds);
            TypeReference<List<HasStockVo>> typeReference = new TypeReference<List<HasStockVo>>() {
            };
            List<HasStockVo> hasStockVos = hasStockResponse.getData(typeReference);
            hasStockMap = hasStockVos.stream().collect(Collectors.toMap(hasStockVo -> hasStockVo.getSkuId(), hasStockVo -> hasStockVo.getHasStock()));
        } catch (Exception e) {
            log.error("远程查询库存系统失败，原因{},库存将默认设置为有库存",e.toString());
        }

        Map<Long, Boolean> finalHasStockMap = hasStockMap;
        List<SkuSearchVo> skuSearchVos = skuInfos.stream().map(skuInfo -> {
            SkuSearchVo skuSearchVo = new SkuSearchVo();
            BeanUtils.copyProperties(skuInfo,skuSearchVo);
            skuSearchVo.setSkuPrice(skuInfo.getPrice());
            skuSearchVo.setSkuImg(skuInfo.getSkuDefaultImg());
            if (finalHasStockMap == null){
                skuSearchVo.setHasStock(true); //默认设置为有库存
            }else{
                skuSearchVo.setHasStock(finalHasStockMap.containsKey(skuInfo.getSkuId())?
                        finalHasStockMap.get(skuInfo.getSkuId()):false);
            }

            //TODO hotScore 暂时设为0
            skuSearchVo.setHotScore(0L);

            BrandEntity brandEntity = brandService.getById(skuInfo.getBrandId());
            skuSearchVo.setBrandName(brandEntity.getName());
            skuSearchVo.setBrandImg(brandEntity.getLogo());

            CategoryEntity category = categoryService.getById(skuInfo.getCatalogId());
            skuSearchVo.setCatalogName(category.getName());

            skuSearchVo.setAttrs(attrValueList);

            return skuSearchVo;
        }).collect(Collectors.toList());

        System.out.println(skuSearchVos);

        //在ES中上架商品

        R r = searchFeignService.saveProduct(skuSearchVos);
        if (r.getCode() == 0){
            //说明远程调用成功，还需将spu状态改为已上架
            this.baseMapper.updateSpuStatus(spuId, ProductConstant.SpuStatus.SPU_UP.getCode());
        }else{
            //说明远程调用失败
            //TODO 接口幂等性？重试机制？
        }

    }

    @Override
    public SpuInfoVo getSpuInfoBySkuId(Long skuId) {
        SpuInfoVo spuInfoVo = this.baseMapper.getSpuInfoBySkuId(skuId);
        return spuInfoVo;
    }
}